// 双色球智能预测系统
const fs = require('fs');
const path = require('path');

/**
 * 读取双色球历史数据
 * @returns {Array} 历史开奖数据数组
 */
function loadLotteryData() {
    try {
        const dataPath = path.join(__dirname, 'lottery_results.json');
        const data = fs.readFileSync(dataPath, 'utf8');
        return JSON.parse(data);
    } catch (error) {
        console.error('读取数据失败:', error);
        return [];
    }
}

/**
 * 将数据转换为标准格式
 * @param {Array} rawData 原始数据
 * @returns {Array} 转换后的标准数据格式
 */
function convertToStandardFormat(rawData) {
    return rawData.map(item => ({
        period: item['期号'],
        date: item['开奖日期'],
        redBalls: item['开奖号码']['红球'].map(num => parseInt(num)),
        blueBall: parseInt(item['开奖号码']['蓝球']),
        firstPrizeCount: item['一等奖注数'],
        firstPrizeAmount: item['一等奖金额'],
        secondPrizeCount: item['二等奖注数'],
        secondPrizeAmount: item['二等奖金额'],
        sales: item['销售额'],
        poolAmount: item['奖池金额']
    }));
}

/**
 * 统计号码出现频率
 * @param {Array} data 历史数据
 * @param {boolean} isBlue 是否为蓝球
 * @returns {Object} 频率统计结果
 */
function calculateFrequency(data, isBlue) {
    const frequency = {};
    const maxNum = isBlue ? 16 : 33;
    
    // 初始化频率计数器
    for (let i = 1; i <= maxNum; i++) {
        frequency[i] = 0;
    }
    
    // 统计频率
    data.forEach(item => {
        if (isBlue) {
            frequency[item.blueBall]++;
        } else {
            item.redBalls.forEach(red => {
                frequency[red]++;
            });
        }
    });
    
    return frequency;
}

/**
 * 分析冷热号码
 * @param {Array} data 历史数据
 * @param {number} recentPeriods 最近期数
 * @returns {Object} 冷热号码分析结果
 */
function analyzeHotColdNumbers(data, recentPeriods = 50) {
    const totalPeriods = data.length;
    const recentData = data.slice(0, recentPeriods);
    
    // 计算整体频率和近期频率
    const overallRedFreq = calculateFrequency(data, false);
    const recentRedFreq = calculateFrequency(recentData, false);
    const overallBlueFreq = calculateFrequency(data, true);
    const recentBlueFreq = calculateFrequency(recentData, true);
    
    // 计算热度指数（近期频率/整体频率的比值）
    const redHotIndex = {};
    const blueHotIndex = {};
    
    for (let i = 1; i <= 33; i++) {
        const overallRate = overallRedFreq[i] / totalPeriods;
        const recentRate = recentRedFreq[i] / recentPeriods;
        redHotIndex[i] = {
            num: i,
            allCount: overallRedFreq[i],
            recentCount: recentRedFreq[i],
            hotIndex: overallRate > 0 ? recentRate / overallRate : 0
        };
    }
    
    for (let i = 1; i <= 16; i++) {
        const overallRate = overallBlueFreq[i] / totalPeriods;
        const recentRate = recentBlueFreq[i] / recentPeriods;
        blueHotIndex[i] = {
            num: i,
            allCount: overallBlueFreq[i],
            recentCount: recentBlueFreq[i],
            hotIndex: overallRate > 0 ? recentRate / overallRate : 0
        };
    }
    
    // 排序并返回结果
    const sortedRed = Object.values(redHotIndex).sort((a, b) => b.hotIndex - a.hotIndex);
    const sortedBlue = Object.values(blueHotIndex).sort((a, b) => b.hotIndex - a.hotIndex);
    
    return {
        hotRed: sortedRed.slice(0, 10),  // 最热的10个红球
        coldRed: sortedRed.slice(-10),   // 最冷的10个红球
        hotBlue: sortedBlue.slice(0, 5), // 最热的5个蓝球
        coldBlue: sortedBlue.slice(-5)   // 最冷的5个蓝球
    };
}

/**
 * 分析连号趋势
 * @param {Array} data 历史数据
 * @param {number} recentCount 最近期数
 * @returns {Object} 连号分析结果
 */
function analyzeConsecutiveNumbers(data, recentCount = 100) {
    const recentData = data.slice(0, recentCount);
    let consecutiveCount = 0;
    let consecutivePairs = {};
    
    recentData.forEach(item => {
        const redBalls = [...item.redBalls].sort((a, b) => a - b);
        let hasConsecutive = false;
        
        for (let i = 0; i < redBalls.length - 1; i++) {
            if (redBalls[i + 1] - redBalls[i] === 1) {
                hasConsecutive = true;
                const pair = `${redBalls[i]}-${redBalls[i + 1]}`;
                consecutivePairs[pair] = (consecutivePairs[pair] || 0) + 1;
            }
        }
        
        if (hasConsecutive) {
            consecutiveCount++;
        }
    });
    
    // 排序连号组合
    const sortedPairs = Object.entries(consecutivePairs)
        .map(([pair, count]) => ({ pair, count }))
        .sort((a, b) => b.count - a.count);
    
    return {
        totalDraws: recentCount,
        consecutiveDraws: consecutiveCount,
        consecutiveRate: Math.round((consecutiveCount / recentCount) * 100 * 100) / 100,
        topConsecutivePairs: sortedPairs.slice(0, 10)
    };
}

/**
 * 基于频率的基础预测
 * @param {Array} data 历史数据
 * @returns {Object} 预测结果
 */
function predictByFrequency(data) {
    const redFreq = calculateFrequency(data, false);
    const blueFreq = calculateFrequency(data, true);
    
    // 将红球按频率排序
    const sortedRedBalls = Object.entries(redFreq)
        .map(([num, count]) => ({ num: parseInt(num), count }))
        .sort((a, b) => b.count - a.count);
    
    // 将蓝球按频率排序
    const sortedBlueBalls = Object.entries(blueFreq)
        .map(([num, count]) => ({ num: parseInt(num), count }))
        .sort((a, b) => b.count - a.count);
    
    // 选择频率较高的6个红球
    const predictedRedBalls = sortedRedBalls.slice(0, 6).map(ball => ball.num).sort((a, b) => a - b);
    
    // 选择频率最高的1个蓝球
    const predictedBlueBall = sortedBlueBalls[0].num;
    
    return { predictedRedBalls, predictedBlueBall };
}

/**
 * 基于冷热号的预测
 * @param {Array} data 历史数据
 * @param {number} hotRedCount 热红球数量
 * @param {number} coldRedCount 冷红球数量
 * @returns {Object} 预测结果
 */
function predictByHotCold(data, hotRedCount = 4, coldRedCount = 2) {
    const hotColdData = analyzeHotColdNumbers(data);
    
    // 随机选择热红球和冷红球
    const selectedHotRed = [];
    const selectedColdRed = [];
    
    // 洗牌算法
    const shuffle = arr => [...arr].sort(() => Math.random() - 0.5);
    
    // 选择热红球
    const shuffledHotRed = shuffle(hotColdData.hotRed.map(ball => ball.num));
    for (let i = 0; i < hotRedCount && i < shuffledHotRed.length; i++) {
        selectedHotRed.push(shuffledHotRed[i]);
    }
    
    // 选择冷红球
    const shuffledColdRed = shuffle(hotColdData.coldRed.map(ball => ball.num));
    for (let i = 0; i < coldRedCount && i < shuffledColdRed.length; i++) {
        selectedColdRed.push(shuffledColdRed[i]);
    }
    
    // 合并并排序红球
    const predictedRedBalls = [...selectedHotRed, ...selectedColdRed].sort((a, b) => a - b);
    
    // 从热蓝球中随机选择一个
    const shuffledHotBlue = shuffle(hotColdData.hotBlue.map(ball => ball.num));
    const predictedBlueBall = shuffledHotBlue[0];
    
    return { predictedRedBalls, predictedBlueBall };
}

/**
 * 生成多注推荐号码
 * @param {Array} data 历史数据
 * @param {number} numOfTickets 推荐注数
 * @returns {Array} 推荐号码数组
 */
function generateRecommendations(data, numOfTickets = 5) {
    const recommendations = [];
    const methods = [
        { name: '频率统计', predictFn: predictByFrequency },
        { name: '冷热搭配(4热2冷)', predictFn: () => predictByHotCold(data, 4, 2) },
        { name: '冷热搭配(3热3冷)', predictFn: () => predictByHotCold(data, 3, 3) },
        { name: '冷热搭配(2热4冷)', predictFn: () => predictByHotCold(data, 2, 4) },
        { name: '频率加权随机', predictFn: () => predictByWeightedRandom(data) } // ← 新增
    ];
    
    // 使用不同方法生成预测
    for (let i = 0; i < numOfTickets; i++) {
        const method = methods[i % methods.length];
        let prediction;
        
        // 确保生成唯一的组合
        do {
            prediction = method.predictFn(data);
        } while (recommendations.some(rec => 
            JSON.stringify(rec.redBalls) === JSON.stringify(prediction.predictedRedBalls) &&
            rec.blueBall === prediction.predictedBlueBall
        ));
        
        recommendations.push({
            redBalls: prediction.predictedRedBalls.map(num => num.toString().padStart(2, '0')),
            blueBall: prediction.predictedBlueBall.toString().padStart(2, '0'),
            method: method.name,
            note: `第${i+1}注: ${method.name}推荐`
        });
    }
    
    return recommendations;
}

/**
 * 计算预测号码的概率得分
 * @param {Array} redBalls 红球号码数组
 * @param {number} blueBall 蓝球号码
 * @param {Array} data 历史数据
 * @returns {number} 概率得分
 */
function calculateProbabilityScore(redBalls, blueBall, data) {
    const totalPeriods = data.length;
    const redFreq = calculateFrequency(data, false);
    const blueFreq = calculateFrequency(data, true);
    
    let score = 0;
    
    // 计算红球概率总和
    redBalls.forEach(ball => {
        score += (redFreq[ball] / totalPeriods) * 6;
    });
    
    // 添加蓝球概率（权重更高）
    score += (blueFreq[blueBall] / totalPeriods) * 2;
    
    return score;
}

/**
 * 主函数
 */
function main() {
    console.log('===== 双色球智能预测系统 =====\n');
    
    // 加载和转换数据
    const rawData = loadLotteryData();
    if (rawData.length === 0) {
        console.log('没有找到有效的数据，程序终止。');
        return;
    }
    
    const data = convertToStandardFormat(rawData);
    console.log(`共分析 ${data.length} 期历史数据\n`);
    
    // 基础分析
    const redFreq = calculateFrequency(data, false);
    const blueFreq = calculateFrequency(data, true);
    
    // 显示频率最高的红球和蓝球
    console.log('📊 号码频率统计');
    const topRedBalls = Object.entries(redFreq)
        .map(([num, count]) => ({ num: parseInt(num), count }))
        .sort((a, b) => b.count - a.count)
        .slice(0, 10);
    
    console.log('\n频率最高的10个红球:');
    topRedBalls.forEach((ball, index) => {
        const probability = (ball.count / data.length * 100).toFixed(2);
        console.log(`${index + 1}. 红球${ball.num}: 出现${ball.count}次 (${probability}%)`);
    });
    
    const topBlueBalls = Object.entries(blueFreq)
        .map(([num, count]) => ({ num: parseInt(num), count }))
        .sort((a, b) => b.count - a.count)
        .slice(0, 5);
    
    console.log('\n频率最高的5个蓝球:');
    topBlueBalls.forEach((ball, index) => {
        const probability = (ball.count / data.length * 100).toFixed(2);
        console.log(`${index + 1}. 蓝球${ball.num}: 出现${ball.count}次 (${probability}%)`);
    });
    
    // 冷热号分析
    const hotColdData = analyzeHotColdNumbers(data);
    console.log('\n🔥 冷热号码分析');
    console.log('\n最近热门红球:');
    hotColdData.hotRed.slice(0, 5).forEach((ball, index) => {
        console.log(`${index + 1}. 红球${ball.num}: 热度指数${ball.hotIndex.toFixed(2)}`);
    });
    
    // 连号趋势分析
    const consecutiveStats = analyzeConsecutiveNumbers(data);
    console.log('\n🔗 连号趋势分析');
    console.log(`最近${consecutiveStats.totalDraws}期内，${consecutiveStats.consecutiveDraws}期出现连号`);
    console.log(`连号出现率: ${consecutiveStats.consecutiveRate}%`);
    
    if (consecutiveStats.topConsecutivePairs.length > 0) {
        console.log('\n最常见的连号组合:');
        consecutiveStats.topConsecutivePairs.slice(0, 5).forEach((item, index) => {
            console.log(`${index + 1}. ${item.pair}: 出现${item.count}次`);
        });
    }
    
    // 生成推荐号码
    console.log('\n🎯 推荐号码');
    const recommendations = generateRecommendations(data, 5);
    
    recommendations.forEach((ticket, index) => {
        console.log(`\n${ticket.note}`);
        console.log(`红球: ${ticket.redBalls.join(' ')}`);
        console.log(`蓝球: ${ticket.blueBall}`);
        console.log(`方法: ${ticket.method}`);
    });
    
    // 保存推荐结果到文件
    const outputPath = path.join(__dirname, 'recommended_ssq_tickets.json');
    try {
        fs.writeFileSync(outputPath, JSON.stringify(recommendations, null, 2));
        console.log(`\n✅ 推荐结果已保存到: ${outputPath}`);
    } catch (error) {
        console.error('保存推荐结果失败:', error);
    }
    
    console.log('\n⚠️  注意: 彩票开奖结果是随机的，此预测仅基于历史数据统计分析，不保证准确性！');
}

/**
 * 按频率加权随机生成一注双色球
 * @param {Array} data 历史数据
 * @returns {Object} { redBalls: string[], blueBall: string }
 */
function predictByWeightedRandom(data) {
  const redFreq = calculateFrequency(data, false);
  const blueFreq = calculateFrequency(data, true);

  // 辅助函数：加权随机选择 n 个不重复元素
  function weightedSampleWithoutReplacement(items, weights, n) {
    if (n > items.length) throw new Error('n cannot exceed items length');
    let selected = [];
    let availableItems = [...items];
    let availableWeights = [...weights];

    for (let i = 0; i < n; i++) {
      // 计算总权重
      const totalWeight = availableWeights.reduce((sum, w) => sum + w, 0);
      if (totalWeight === 0) {
        // 如果所有权重为0（理论上不会发生），退化为均匀随机
        const idx = Math.floor(Math.random() * availableItems.length);
        selected.push(availableItems[idx]);
        availableItems.splice(idx, 1);
        availableWeights.splice(idx, 1);
        continue;
      }

      // 生成 [0, totalWeight) 的随机数
      let rand = Math.random() * totalWeight;
      let cumulative = 0;
      let chosenIndex = 0;
      for (let j = 0; j < availableWeights.length; j++) {
        cumulative += availableWeights[j];
        if (rand <= cumulative) {
          chosenIndex = j;
          break;
        }
      }

      selected.push(availableItems[chosenIndex]);
      availableItems.splice(chosenIndex, 1);
      availableWeights.splice(chosenIndex, 1);
    }

    return selected.sort((a, b) => a - b);
  }

  // 红球：1~33，权重为频率
  const redNumbers = Array.from({ length: 33 }, (_, i) => i + 1);
  const redWeights = redNumbers.map(num => redFreq[num] || 1); // 避免除零，最低权重设为1

  // 蓝球：1~16
  const blueNumbers = Array.from({ length: 16 }, (_, i) => i + 1);
  const blueWeights = blueNumbers.map(num => blueFreq[num] || 1);

  // 随机选6红（不重复，加权）
  const predictedRedBalls = weightedSampleWithoutReplacement(redNumbers, redWeights, 6);
  // 随机选1蓝（加权）
  const totalBlueWeight = blueWeights.reduce((sum, w) => sum + w, 0);
  let randBlue = Math.random() * totalBlueWeight;
  let cumBlue = 0;
  let predictedBlueBall = 1;
  for (let i = 0; i < blueNumbers.length; i++) {
    cumBlue += blueWeights[i];
    if (randBlue <= cumBlue) {
      predictedBlueBall = blueNumbers[i];
      break;
    }
  }

  return {
    "predictedRedBalls": predictedRedBalls.map(n => n.toString().padStart(2, '0')),
    "predictedBlueBall": predictedBlueBall.toString().padStart(2, '0')
  };
}

// 执行主函数
if (require.main === module) {
    main();
}

// 导出函数供其他模块使用
module.exports = {
    loadLotteryData,
    convertToStandardFormat,
    calculateFrequency,
    analyzeHotColdNumbers,
    analyzeConsecutiveNumbers,
    predictByFrequency,
    predictByHotCold,
    generateRecommendations,
    calculateProbabilityScore,
    main
};